/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.siseventos.dao;

import br.siseventos.dao.util.HibernateUtil;
import br.siseventos.util.EntityNameHelper;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import org.hibernate.*;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Component;

public abstract class BaseDao<T> implements Dao<T>, Serializable {
    // Campos

    private Class<T> classe;

    // Construtor
    public BaseDao() {
        // Criando o objeto Sessão
        //sessao = HibernateUtil.getSession();

        // Buscando a classe passada como parâmetro genérico
        classe = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

    }

    // Construtor com injeção de dependência
    // Getters e Setters
    // Serviço
    public T consultar(int id) throws Exception {
        Session sessao = HibernateUtil.getSession();
        Transaction t = null;
        T o = null;
        try {
            t = sessao.beginTransaction();
            o = (T) sessao.get(classe, new Integer(id));
            t.commit();
        } catch (Exception e) {
            if (t != null) {
                try {
                    t.rollback();
                } catch (Exception ex) {
                }
            }
            throw e;
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }
        return o;
    }

    public List<T> consultar(int indiceInicial, int quantidadeResultados) throws Exception {
        Session sessao = HibernateUtil.getSession();
        Transaction t = null;
        List<T> o = null;
        try {
            t = sessao.beginTransaction();
            Criteria c = sessao.createCriteria(classe);
            c.setFirstResult(indiceInicial);
            c.setMaxResults(quantidadeResultados);
            o = (List<T>) c.list();
            t.commit();
        } catch (Exception e) {
            if (t != null) {
                try {
                    t.rollback();
                } catch (Exception ex) {
                }
            }
            throw e;
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }


        return o;
    }

    public List<T> consultar(String nome) throws Exception {
        Session sessao = HibernateUtil.getSession();
        Transaction t = null;
        List<T> o = null;
        try {
            t = sessao.beginTransaction();
            Criteria c = sessao.createCriteria(classe).add(Restrictions.like("nme".concat(classe.getSimpleName().substring(2)), nome));
            o = (List<T>) c.list();
            t.commit();
        } catch (Exception e) {
            if (t != null) {
                try {
                    t.rollback();
                } catch (Exception ex) {
                }
            }
            throw e;
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }

        return o;
    }

    public List<T> consultarTodos() throws Exception {
        Session sessao = HibernateUtil.getSession();
        Transaction t = null;
        List<T> o = null;
        try {
            t = sessao.beginTransaction();
            Criteria c = sessao.createCriteria(classe);
            // Ordenando pela última inserção
            String id = "idt" + classe.getSimpleName().substring(2);
            c.addOrder(Order.desc(id));
            o = (List<T>) c.list();
            t.commit();
        } catch (Exception e) {
            if (t != null) {
                try {
                    t.rollback();
                } catch (Exception ex) {
                }
            }
            throw e;
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }


        return o;
    }

    public Long incluir(T obj) throws Exception {
        Session sessao = HibernateUtil.getSession();
        Transaction t = null;
        Long id = null;
        try {
            t = sessao.beginTransaction();
            id = Long.parseLong(((Integer) sessao.save(obj)).toString());
            t.commit();
        } catch (Exception e) {
            if (t != null) {
                try {
                    t.rollback();
                } catch (Exception ex) {
                }
            }
            throw e;
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }


        return id;
    }

    public void excluir(T obj) throws Exception {
        Session sessao = HibernateUtil.getSession();
        Transaction t = null;
        try {
            t = sessao.beginTransaction();
            sessao.delete(obj);
            t.commit();
        } catch (HibernateException e) {
            if (t != null) {
                t.rollback();
            }
            throw e;
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }

    }

    public void excluir(int id) throws Exception {
        Session sessao = HibernateUtil.getSession();
        Transaction t = null;
        try {
            t = sessao.beginTransaction();
            sessao.delete((T) sessao.get(classe, new Integer(id)));
            t.commit();
        } catch (HibernateException e) {
            if (t != null) {
                t.rollback();
            }
            throw e;
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }
    }

    public void alterar(T obj) throws Exception {
        Session sessao = HibernateUtil.getSession();
        Transaction t = null;
        try {
            t = sessao.beginTransaction();
            sessao.saveOrUpdate(obj);
            t.commit();
        } catch (Exception e) {
            if (t != null) {
                try {
                    t.rollback();
                } catch (Exception ex) {
                }
            }
            throw e;
        } finally {
            if (sessao != null) {
                sessao.close();
            }
        }

    }

    // Util
    public String getNomeClasse() {
        return classe.getSimpleName();
    }
}
